home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ccas01.arc / C.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-03-15  |  8.4 KB  |  431 lines

  1.     TITLE    C - Initiate execution of a Lattice C program
  2.     SUBTTL    Copyright 1982 by Lattice, Inc.
  3.     NAME    C
  4.     INCLUDE    DOS.MAC
  5. ;**
  6. ;
  7. ; name        C -- initiate execution of C program
  8. ;
  9. ; description    This is the main module for a C program on the
  10. ;        MS-DOS implementation.  It initializes the segment
  11. ;        registers, sets up the stack, and calls the C main
  12. ;        function _main with a pointer to the remainder of
  13. ;        the command line.
  14. ;
  15. ;        Also defined in this module: the exit entry point
  16. ;        XCEXIT, and the stack overflow entry XCOVF.
  17. ;
  18. ;**
  19.      IF    S8086
  20. PGROUP    GROUP    BASE,PROG
  21. BASE    SEGMENT    WORD PUBLIC 'PROG'
  22.     DW     0
  23. BASE    ENDS
  24.     ENDIF
  25.  
  26.     IF    P8086
  27. BASE    SEGMENT    WORD
  28.     DW    1
  29. BASE    ENDS
  30.     ENDIF
  31.  
  32.     IF    D8086
  33. CGROUP    GROUP    BASE,CODE
  34. BASE    SEGMENT    WORD PUBLIC 'CODE'
  35.     DW    2
  36. BASE    ENDS
  37.     ENDIF
  38.  
  39.     IF    L8086
  40. BASE    SEGMENT WORD
  41.     DW    3
  42. BASE    ENDS
  43.     ENDIF
  44.  
  45.     IF    LPROG
  46.     EXTRN    _MAIN:FAR
  47. ECODE    EQU    4        ;offset of error code for XCEXIT
  48.     ELSE
  49. ECODE    EQU    2        ;offset of error code for XCEXIT
  50.     ENDIF
  51.  
  52. DGROUP    GROUP    DATA,STACK
  53.  
  54.  
  55. ;
  56. ; The data segment defines locations which contain the offsets
  57. ; of the base and top of the stack.
  58. ;
  59. DATA    SEGMENT PARA PUBLIC 'DATA'
  60.     EXTRN    _STACK:WORD
  61.     PUBLIC    _VER,_TOP,_BASE,_INAME,_ONAME,_PSP,_MBASE,_MNEXT,_MSIZE
  62. NULL    DW    0
  63. _VER    DB    "Lattice C 2.00"
  64. _TOP    DW    0            ; top of stack (relative to SS)
  65. _BASE    DW    0            ; base of stack (relative to DS)
  66. _INAME    DB    32 DUP(0)        ; input file name
  67. _ONAME    DB    32 DUP(0)        ; output file name
  68. _PSP    DD    0            ; program segment prefix pointer
  69.     IF    LDATA
  70. _MBASE    DD    0            ; base of memory pool
  71. _MNEXT    DD    0            ; next available memory location
  72.     ELSE
  73. _MBASE    DW    0            ; base of memory pool
  74. _MNEXT    DW    0            ; next available memory location
  75.     ENDIF
  76. _MSIZE    DD     0             ; number of bytes left in pool
  77.     IF    MSDOS EQ 2
  78. _ENV    DD    0            ; pointer to environment
  79.     ENDIF
  80. STKERR    DB    "Invalid stack size",0DH,0AH,"$"
  81. NAMERR    DB     "Invalid I/O redirection",0DH,0AH,"$"
  82. MEMERR    DB    "Insufficient memory",0DH,0AH,"$"
  83. OVFERR    DB    "*** STACK OVERFLOW ***",0DH,0AH,"$"
  84. DATA    ENDS
  85. ;
  86. ; The stack segment is included to prevent the warning from the
  87. ; linker, and also to define the base (lowest address) of the stack.
  88. ;
  89. STACK    SEGMENT STACK 'DATA'
  90. SBASE    DW    128 DUP (?)
  91. STACK    ENDS
  92. STKMIN    EQU    512            ; minimum stack size
  93.  
  94. TAB    EQU    09H            ; tab character
  95. ;
  96. ; The main program must set up the initial segment registers
  97. ; and the stack pointer, and set up a far return to the MS-DOS
  98. ; exit point at ES:0.  The command line bytes from the program
  99. ; segment prefix are moved onto the stack, and a pointer to
  100. ; them supplied to the C main module _main (which calls main).
  101. ;
  102.     IF    S8086
  103. PROG    SEGMENT    BYTE PUBLIC 'PROG'
  104.     ASSUME    CS:PGROUP
  105.     ENDIF
  106.  
  107.     IF    D8086
  108. CODE    SEGMENT    BYTE PUBLIC 'CODE'
  109.     ASSUME    CS:CGROUP
  110.     ENDIF
  111.  
  112.     IF    P8086
  113. _CODE    SEGMENT    BYTE
  114.     ASSUME    CS:_CODE
  115.     ENDIF
  116.  
  117.     IF    L8086
  118. _PROG    SEGMENT    BYTE
  119.     ASSUME    CS:_PROG
  120.     ENDIF
  121.  
  122.     ASSUME    DS:DGROUP
  123.  
  124.     IF    LPROG EQ 0
  125.     EXTRN    _MAIN:NEAR
  126.     ENDIF
  127.  
  128.     PUBLIC    C
  129. C    PROC    FAR
  130.     CLI
  131.     MOV    AX,DGROUP        ; set ds base
  132.     MOV    DS,AX
  133.     MOV    AX,STACK
  134.     MOV    SS,AX            ; set ss base
  135.     MOV    SP,256            ; temporarily set stack pointer
  136.     STI
  137.     MOV    AX,OFFSET DGROUP:SBASE    ; set _BASE to top of data
  138.     MOV    _BASE,AX
  139.     MOV    _PSP+2,ES        ; set up pointer to prog seg prefix
  140.     IF    MSDOS EQ 2
  141.     MOV    AX,ES:[2CH]
  142.     MOV    _ENV+2,AX        ; set up pointer to environment
  143.     ENDIF
  144. ;
  145. ; Examine command line
  146. ;
  147.     MOV    SI,80H            ; check command line
  148.     MOV    CL,ES:[SI]
  149.     XOR    CH,CH
  150.     JCXZ    M12            ; branch if null
  151. M1:    INC    SI            ; scan for first arg
  152.     MOV    AL,ES:[SI]
  153.     IF    MSDOS EQ 1
  154.     CMP    AL,'<'
  155.     JE    M2            ; branch if input file name
  156.     CMP    AL,'>'
  157.     JE    M3            ; branch if output file name
  158.     ENDIF
  159.     CMP    AL,'='
  160.     JE    M4            ; branch if stack size
  161.     CMP    AL,' '
  162.     JE    M11            ; branch if white space
  163.     CMP    AL,TAB
  164.     JNE    M12            ; branch if normal arg
  165. M11:    DEC    CX
  166.     JG    M1
  167.     XOR    CX,CX
  168. M12:    JMP    M5            ; branch if no args found
  169.     IF    MSDOS EQ 1
  170. ;
  171. ; Get input file name
  172. ;
  173. M2:    MOV    DI,OFFSET DGROUP:_INAME
  174.     JMP    M31
  175. ;
  176. ; Get output file name
  177. ;
  178. M3:     MOV    DI,OFFSET DGROUP:_ONAME
  179. ;
  180. ; Save file name in data area
  181. ;
  182. M31:    XOR    AH,AH
  183. M32:    DEC    CX
  184.     JZ    M33
  185.     INC    SI
  186.     MOV    AL,ES:[SI]
  187.     CMP    AL,' '
  188.     JZ    M33
  189.     CMP    AL,TAB
  190.     JZ    M33
  191.     MOV    DS:[DI],AL
  192.     INC    DI
  193.     INC    AH
  194.     CMP    AH,32
  195.     JE    M34
  196.     JMP    M32
  197. M33:    MOV    BYTE PTR DS:[DI],0
  198.     JMP    M11
  199. M34:    MOV    DX,OFFSET DGROUP:NAMERR
  200.     JMP    ABORT
  201.     ENDIF
  202. ;
  203. ; Get stack size from command line
  204. ;
  205. M4:    XOR    BX,BX            ; get stack size arg
  206. M41:    DEC    CX
  207.     JZ    M42
  208.     INC    SI
  209.     MOV    AL,ES:[SI]
  210.     CMP    AL,' '
  211.     JE    M42
  212.     CMP    AL,TAB
  213.     JE    M42
  214.     SUB    AL,'0'
  215.     JL    M43
  216.     CMP    AL,9
  217.     JG    M43
  218.     ADD    BX,BX
  219.     JC    M43
  220.     MOV    DX,BX
  221.     ADD    BX,BX
  222.     JC    M43
  223.     ADD    BX,BX
  224.     JC    M43
  225.     ADD    BX,DX
  226.     JC    M43
  227.     XOR    AH,AH
  228.     ADD    BX,AX
  229.     JC    M43
  230.     JMP    M41
  231. M42:    OR    BX,BX
  232.     JZ    M43            ; branch if stack size arg is null
  233.     MOV    _STACK,BX
  234.     JMP    M11
  235. M43:    MOV    DX,OFFSET DGROUP:STKERR
  236.     JMP    ABORT
  237. ;
  238. ; Set up the stack
  239. ;
  240. M5:    MOV    BX,_STACK        ; get stack size
  241.     SHR    BX,1            ; make size even
  242.     ADD    BX,BX
  243.     CMP    BX,STKMIN
  244.     JA    M51
  245.     MOV    BX,STKMIN        ; use default if too small
  246.     MOV    _STACK,BX
  247. M51:    MOV    DX,ES:2            ; compute available paragraphs
  248.     IF    LDATA
  249.     MOV    AX,SS
  250.     ELSE
  251.     MOV    AX,DS
  252.     ENDIF
  253.     SUB    DX,AX
  254.     TEST    DX,0F000H
  255.     JNZ    M52            ; branch if greater than 64Kbytes
  256.     SHL    DX,1            ; convert to bytes
  257.     SHL    DX,1
  258.     SHL    DX,1
  259.     SHL    DX,1
  260.     JMP    M53
  261. M52:    MOV    DX,0FFF0H        ; use largest value
  262.     IF    LDATA
  263. M53:    CMP    DX,BX            ; check if stack will fit
  264.     JA    M55
  265.     ELSE
  266. M53:    MOV    AX,_BASE        ; check if stack will fit
  267.     ADD    AX,BX
  268.     JC    M54
  269.     CMP    DX,AX
  270.     JA    M55
  271.     ENDIF
  272. M54:    MOV    DX,OFFSET DGROUP:MEMERR    ; abort if insufficient memory
  273.     JMP    ABORT
  274.     IF    LDATA
  275. M55:    MOV    _TOP,BX            ; set top-of-stack
  276.     MOV    SP,BX            ; set stack pointer
  277.     ELSE
  278. M55:    MOV    _TOP,DX            ; set top-of-stack
  279.     CLI
  280.     MOV    AX,DS
  281.     MOV    SS,AX
  282.     MOV    SP,DX            ; set stack pointer
  283.     STI
  284.     ENDIF
  285. ;
  286. ; Set up memory allocation pointers
  287. ;
  288.      MOV    DX,CX            ; save command byte count
  289.     IF    LDATA
  290.     MOV    AX,_TOP            ; compute mem pool base segment number
  291.     ADD    AX,15
  292.     MOV    CL,4
  293.     SHR    AX,CL
  294.     MOV    BX,SS
  295.     ADD    AX,BX
  296.     MOV    _MBASE+2,AX
  297.     MOV    _MNEXT+2,AX
  298.     MOV    BX,ES:2            ; get top segment number
  299.     SUB    BX,AX            ; compute memory pool size
  300.     JBE    M54            ; branch if insufficient memory
  301.     MOV    CL,4            ; compute number of bytes
  302.     ROL    BX,CL
  303.     MOV    AX,BX
  304.     AND    AX,15
  305.     AND    BX,0FFF0H
  306.     MOV    _MSIZE,BX
  307.     MOV    _MSIZE+2,AX
  308.     ELSE
  309.     MOV    AX,_BASE        ; set up memory pool for small data
  310.     MOV    _MBASE,AX
  311.     MOV    _MNEXT,AX
  312.     MOV    BX,_TOP
  313.     SUB    BX,AX
  314.     SUB    BX,_STACK
  315.     JB    M54
  316.     MOV    _MSIZE,BX
  317.     ENDIF
  318. ;
  319. ; Put return address at top of stack
  320. ;
  321.     PUSH    ES            ; return is to 1st word of prog prefix
  322.     XOR    AX,AX
  323.     PUSH    AX
  324.     MOV    BP,SP            ; BP contains stack linkage
  325. ;
  326. ; copy command line to stack
  327. ;
  328.     MOV    BX,DX            ; get residual command line length
  329.     MOV    CX,DX
  330.     ADD    BX,4            ;3 bytes additional, 1 for rounding
  331.     AND    BX,0FFFEH         ;force even number of bytes
  332.     SUB    SP,BX             ;allocate space on stack
  333.     MOV    DI,SP
  334.     MOV    BYTE PTR SS:[DI],'c'    ;store dummy program name
  335.     INC    DI
  336.     JCXZ    M8             ;skip if no bytes to move
  337.     MOV    BYTE PTR SS:[DI],' '
  338.     INC    DI
  339. M7:    MOV    AL,ES:[SI]         ;move bytes to stack
  340.     MOV    SS:[DI],AL
  341.     INC    SI
  342.     INC    DI
  343.     LOOP    M7
  344. M8:    MOV    BYTE PTR SS:[DI],0    ; append null byte
  345.  
  346. ;
  347. ; set up args for _main and call it
  348. ;
  349.     MOV    AX,SP            ; push pointer to command line
  350.     IF    LDATA
  351.     PUSH    SS
  352.     ENDIF
  353.     PUSH    AX
  354.     PUSH    DS            ; make ES same as DS
  355.     POP    ES
  356.     CALL    _MAIN             ;call C main
  357.     IF    MSDOS EQ 2
  358.     MOV    AX,4C00H
  359.     INT    21H            ; exit with zero code
  360.     ELSE
  361.     MOV    SP,BP             ;restore ptr to far return
  362.     RET                ;return to MS-DOS
  363.     ENDIF
  364. ;
  365. ; Come here to abort 
  366. ;
  367. ABORT:    MOV    AH,9            ; print error message
  368.     INT    21H
  369.     IF    MSDOS EQ 2
  370.     MOV    AX,4C01H
  371.     INT    21H
  372.     ELSE
  373.     PUSH    ES
  374.     XOR    AX,AX
  375.     PUSH    AX
  376.     RET
  377.     ENDIF
  378. C    ENDP
  379.     PAGE
  380. ;**
  381. ;
  382. ; name        XCOVF -- terminate execution after stack overflow
  383. ;
  384. ; description    This entry point is reached from a C module when its
  385. ;        entry sequence detects a stack overflow.  Control is
  386. ;        passed to XCOVF by a direct jump.
  387. ;
  388. ;**
  389.     PUBLIC    XCOVF
  390. XCOVF    PROC    FAR
  391.     MOV    AX,_TOP
  392.     SUB    AX,4
  393.     MOV    SP,AX        ; RESET STACK POINTER
  394.     MOV    DX,OFFSET DGROUP:OVFERR
  395.     MOV    AH,9
  396.     INT    21H        ; GENERATE ERROR MESSAGE
  397.     IF    MSDOS EQ 2
  398.     MOV    AX,4C01H
  399.     INT    21H        ; EXIT WITH ERROR CODE
  400.     ELSE
  401.     RET            ; RETURN TO MS-DOS
  402.     ENDIF
  403. XCOVF    ENDP
  404. ;**
  405. ;
  406. ; name        XCEXIT -- terminate execution of C program
  407. ;
  408. ; description    This function terminates execution of the current
  409. ;        program by returning to MS-DOS.  The error code
  410. ;        argument normally supplied to XCEXIT is ignored 
  411. ;        in this implementation.
  412. ;
  413. ;**
  414.     PUBLIC    XCEXIT
  415. XCEXIT    PROC    FAR
  416.     IF    MSDOS EQ 2
  417.     MOV    BP,SP
  418.     MOV    AX,[BP+ECODE]    ; GET ERROR CODE
  419.     MOV    AH,4CH
  420.     INT    21H        ; EXIT
  421.     ELSE
  422.     MOV    AX,_TOP
  423.     SUB    AX,4
  424.     MOV    SP,AX
  425.     RET
  426.     ENDIF
  427. XCEXIT    ENDP
  428.  
  429.     ENDPS
  430.     END    C
  431.